import axios from 'axios';
import { App, reactive } from 'vue';
import { Package, Demo } from '@/types/package';

const loadDocFuncMap = import.meta.glob('/packages/**/*.md');
const loadLogoFuncMap = import.meta.glob('/packages/**/logo.*');
const loadDemoFuncMap = import.meta.glob('/packages/**/demo/**.vue');
const packages = reactive({} as Partial<Package>);

// 生成文档动态加载函数
Object.keys(loadDocFuncMap).forEach(async (path) => {
  const matchPath = path.match(/[^/]+\/([^/]+)\//) as string[];
  const pkgName = matchPath[1];
  const loadDocFunc = loadDocFuncMap[path];
  if (packages[pkgName]) {
    packages[pkgName].loadDocFunc = loadDocFunc;
  } else {
    packages[pkgName] = {
      loadDocFunc,
    };
  }
});

// 生成LOGO动态加载函数
Object.keys(loadLogoFuncMap).forEach(async (path: string) => {
  const matchPath = path.match(/[^/]+\/([^/]+)\//) as string[];
  const pkgName = matchPath[1];
  const loadLogoFunc = loadLogoFuncMap[path];
  if (packages[pkgName]) {
    packages[pkgName].loadLogoFunc = loadLogoFunc;
  } else {
    packages[pkgName] = {
      loadLogoFunc,
    };
  }
});

// 生成 demo 动态加载函数
Object.keys(loadDemoFuncMap).forEach((path: string) => {
  const matchPath = path.match(/[^/]+\/([^/]+)\/[^/]+\/([^/]+)\./) as string[];
  const pkgName = matchPath[1];
  const name = matchPath[2];
  const loadDemoFunc = loadDemoFuncMap[path];
  const loadCodeFunc = () =>
    import.meta.env.MODE !== 'location'
      ? axios.get(`${import.meta.env.VITE_BASE_URL}${path}`)
      : import(/* @vite-ignore */ `${path}?raw`);
  const demoInfo: Demo = {
    name,
    loadDemoFunc,
    loadCodeFunc,
  };
  if (packages[pkgName]) {
    packages[pkgName].demos = packages[pkgName].demos || [];
    packages[pkgName].demos.push(demoInfo);
  } else {
    packages[pkgName] = {
      demos: [demoInfo],
    };
  }
});

// 处理demo源码
function getDemoInfo(pkgName: string, sourceCode) {
  const infoReg = /\/\*\*[\s\S]*?@title[\s\S]*?@desc[\s\S]*?\*\//;
  const infoStr = (sourceCode.match(infoReg) || [''])[0];
  const title = (infoStr.match(/@title (.*)[\n\r\n]/) || [])[1];
  const desc = (infoStr.match(/@desc (.*)[\n\r\n]/) || [])[1];
  const code = sourceCode
    .replace(infoStr, '')
    .replace(/\n\s*\n/g, '\n')
    .replace(`from '..'`, `from '@sscd/${pkgName}'`)
    .replaceAll(`from '../index'`, `from '@sscd/${pkgName}'`)
    .replace(`from '../index.ts'`, `from '@sscd/${pkgName}'`)
    .replace(`from '../index.vue'`, `from '@sscd/${pkgName}'`)
    .replace(`from 'packages/${pkgName}/index.vue'`, `from '@sscd/${pkgName}'`);
  return { title, desc, code };
}

// 动态加载组件文档
export async function loadDoc() {
  return new Promise((resolve) => {
    const loadDocList = Object.keys(packages).map((pkgName) => {
      return packages[pkgName].loadDocFunc().then((docModule) => {
        packages[pkgName].name = pkgName;
        packages[pkgName].title = docModule.attributes.title;
        packages[pkgName].category = docModule.attributes.category;
        packages[pkgName].description = docModule.attributes.description;
        packages[pkgName].docHtml = docModule.html;
        return docModule;
      });
    });
    Promise.all(loadDocList).then(() => {
      resolve(loadDocList);
    });
  });
}

// 动态加载Logo
export async function loadLogo() {
  return new Promise((resolve) => {
    const loadLogoList = Object.keys(packages).map((pkgName) => {
      if (!packages[pkgName].loadLogoFunc) {
        return Promise.resolve();
      }
      return packages[pkgName].loadLogoFunc().then((logoModule) => {
        packages[pkgName].logo = logoModule.default;
        return logoModule.default;
      });
    });
    Promise.all(loadLogoList).then(() => {
      resolve(loadLogoList);
    });
  });
}

// 动态加载组件demo
export async function loadDemo(pkgName: string, app: App) {
  return new Promise((resolve) => {
    const demoNames: string[] = [];
    const loadDemoFuncList = (packages[pkgName].demos || []).map((demo, index) => {
      demoNames[index] = demo.name;
      return demo.loadDemoFunc();
    });
    const loadCodeFuncList = (packages[pkgName].demos || []).map((demo) => {
      return demo.loadCodeFunc();
    });
    Promise.all([Promise.all(loadDemoFuncList), Promise.all(loadCodeFuncList)]).then(
      ([demos, codes]) => {
        demos.forEach((demoModule, index) => {
          app.component(demoNames[index], demoModule.default);
        });
        codes.forEach((codeRes, index) => {
          const { title, desc, code } = getDemoInfo(pkgName, codeRes.data || codeRes.default);
          packages[pkgName].demos[index].title = title;
          packages[pkgName].demos[index].desc = desc;
          packages[pkgName].demos[index].code = code;
        });
        resolve([demos, codes]);
      }
    );
  });
}

export default packages;
